<?php 

namespace controladores;


use fcf\Controller as Controller;
use fcf\view as View;
use dao\fcfDao as fcfDao;
use utils\Utils;
use dao\usuariosDao;
use utils\sesiones;
use utils\LoginUtils;


class Login extends Controller{
	
	var $error; //mensaje de error que mostramos en la vista del login
	var $usuario_bbdd; //guardamos la informacion del usuario recuperado de la base de datos
	static $usuariosDao;
	public static $tiempo_expiracion = 1600; //definimos en segundos el tiempo de expiracion de la sesion
	
	function __construct(){
		$this->usuariosDao = new usuariosDao();
	}
	
	/*
	* Vista del formulario de login
	* @data - info enviada a la vista del formulario donde mostraremos mensajes(sesion caducada, sesion cerrada ..)
	*/
	public static function formularioLogin($data = null){
		//Si no existe usuario logeado redireccionamos a pantalla login
		if(!Login::usuario()){  
			View::render('login','login/formulario_acceso',$data);
		}else{ // Si el usuario ya se ha logeado
			header('Location: '.URL);
		}
	}
		
	/*
	* Recibe los datos del formulario de login
	* @usr   usuario
	* @passwd password
	* 
	*/
	public function checkLogin(){
		$data = new \stdClass();
		//recogemos parametros
		$info = Utils::getPost(); 
		//Realiza comprobaciones, si son correctas añadimos el usuario a la sesion
		if($usuario = $this->validaciones($info)){ 
			$this->setCookie();
			$this->setInfoUsrSesion();//añade info usuario a la sesion
			$this->usuariosDao->registroLogin(self::usuario());//guardamos en el historial el inicio de sesion del usuario
			Sesiones::crearFicheroSesion();
			$this->redireccion(); //una vez comprobado el login y añadida la sesion, redireccionamos a la web
		}else{
			$data->mensaje = $this->error; //añadimos error para enviar a la vista
			self::formularioLogin($data); //al fallar la validacion mostraremos el formulario de login y el mensaje de error
		}
	}
	
	/*
	* Realiza todas las validaciones con los parametros recibidos del formulario del login.Retorna true.
	* @info - parametros recibidos del formulario
	* @usuario_bbdd - info usuario de la base de datos ( si existe ) selecionada con los datos introducidos por el usuario
	*/
	function validaciones($info){
		
		//comprueba si el string usuario es valido
		if(!Utils::validarString($info->usr)){ $this->error = "USUARIO NO VALIDO";  return false;} 
		//comprueba si el string password es valido
		if(!Utils::validarString($info->passwd)){ $this->error = "CONTRASEÑA NO VALIDA";  return false;} 
		
		//buscamos en la BBDD si existe el usuario introducido por nombre
		$usuario_bbdd = $this->usuariosDao->getUsuarioPorNombre($info->usr); 
		
		if(empty($usuario_bbdd)){
			$this->error = "L'USUARI NO EXISTEIX";
			return false;
		}

		//Si hay un error en la query o al conectar
		if($usuario_bbdd == "ERRORCON"){ 
			$this->error = "ERROR AL CONECTAR";  
			return false; 
		} 
		
		if($usuario_bbdd->intentos_fallidos >=5){
			$this->error = "USUARIO BLOQUEADO CONTACTAR CON ADMINISTRADOR";
			return false;
		}
		
		//si al comparar el usuario introducido con el usuario de la base de datos, no es valido, retorna false
		//if($info->usr != $usuario_bbdd->usuario or $info->passwd != $usuario_bbdd->password){ 
		if(!Utils::checkPassword($info->passwd,$usuario_bbdd->password)){
				$this->error = "CLAU D'ACCÉS NO VÀLIDA"; 
				//incrementamos intentos fallidos
				if($usuario_bbdd->intentos_fallidos <5){
					$this->intentoFallido($info->usr);
				}
				return false; 
		}
		//si el usuario y la contraseña recibidas coinciden, return true
		$this->usuario_bbdd=$usuario_bbdd;
		return true; 
		
	}

	/*
	* Comprueba si la sesion ha caducado.
	*/
	public static function comprobarCaducidadSesion(){
		
		$fecha_actual = time();
		//recoge variable sesion con la fecha de caducidad del usuario
		$caduca = Login::usuario()->tiempo_expiracion; 
		
		if($fecha_actual <= $caduca){
			return true; //true si la sesion ha caducado 
		}
	}

	/*
	* Añade la información del usuario requerida a la variable de sesion $_SESSION['usuario']
	* @logged - marca al usuario como logeado
	* @tiempo_expiracion - cuando caduca sesion
	*/
	function setInfoUsrSesion(){

		$hora_actual = time();
		$id_usuario = $this->usuario_bbdd->id;
		
		$data = new \stdClass();
		$data->tmp = hash(METODO_ENCRIPTACION,ENCRYPT_KEY.$id_usuario.$hora_actual);
		$data->id = $id_usuario;
		$data->usr = $this->usuario_bbdd->usuario;
		$data->logged = true;
		$data->inicio_sesion = $hora_actual;
		$data->ultima_conexion = $hora_actual;
		$data->tiempo_expiracion = self::setCaducidadSesion();
		$data->navegador = $_SERVER['HTTP_USER_AGENT'];
		$_SESSION[SESSION_USUARIO] = $data;
	}
	
	/*
	* Determina el tiempo de caducidad de la sesion
	* @caducidad 
	* 3600 - 1hora | 60 -  1 min | 1 - 1 segundo
	*/
	public static function setCaducidadSesion(){
		return time()+self::$tiempo_expiracion; 
	}
	
	/*
	* Renueva la sesion del usuario 
	*/
	public static function renovarSesion(){
	
		$_SESSION[SESSION_USUARIO]->ultima_conexion = $_SESSION[SESSION_USUARIO]->tiempo_expiracion-self::$tiempo_expiracion;
		$_SESSION[SESSION_USUARIO]->tiempo_expiracion = self::setCaducidadSesion();
		Sesiones::crearFicheroSesion();
	}
	
	/*
	* si venimos de otra URL y no podemos acceder(perdida sesion,entramos directamente a la url). Hace la redireccion
	* si no habia ruta anterior nos redirecciona a la portada	
	*/
	public function redireccion(){
		
		if(!empty($_SERVER['HTTP_REFERER'] && $_SERVER['HTTP_REFERER'] != URL.'tancar-sessio' &&  $_SERVER['HTTP_REFERER'] != URL.'iniciar-sesion')){
			header('Location:'.$_SERVER['HTTP_REFERER']);
			exit();
		}else{
			header('Location:'.URL);
			exit();
		}		
	}

	/*
	* Cierra sesión activa y muestra de nuevo formulario de acceso
	*/
	function cerrarSesion(){
		//Si el usuario existe, cerramos sesion
		if(Login::usuario()){
			self::destroySesion();
			$data = new \stdClass();
			$data->mensaje = "SESSIÓ TANCADA";
		}
		
		self::formularioLogin($data);
	}

	/*
	* Recupera la información guardara en la sesion del usuario
	*/
	public static function usuario(){
		
		if(isset($_SESSION[SESSION_USUARIO])){ 
			return $_SESSION[SESSION_USUARIO];
		}else{
			return false;
		}
	}
	
	/*
	* Si el usuario introduce una contraseña incorrecta incrementa en 1 el total de intentos fallidos en la tabla usuarios
	* a los 5 intentos fallidos se bloquea
	*/
	public function intentoFallido($nombre){

		$info = $this->usuariosDao->getUsuarioPorNombre($nombre);
		$this->usuariosDao->incrementarIntentoFallido($info->id);
	}
	
	/*
	* Destruye sesion
	*/
	public static function destroySesion(){
		unset($_SESSION[SESSION_USUARIO]);
		session_destroy();
	}
	
	/*
	* Añadimos una cookie como seguridad necesaria para mantener el usuario logeado.
	* Añade un valor encriptado usando dos valores ENCRYPT_KEY y COOKIE_STRING , modificables en el fichero de configuracion
	*/
	public static function setCookie(){

		//Si existe la cookie, la eliminamos
		if (isset($_COOKIE[SESSION_LOGIN])) {
			setcookie (SESSION_LOGIN,"", time() - 3600);
		}
		//añadimos cookie
		setcookie(SESSION_LOGIN,hash(METODO_ENCRIPTACION,ENCRYPT_KEY.Login::usuario()->usuario));
	}
	
	/*
	* Comprueba si el valor de la cookie es el correcto y no ha sido modificada 
	*/
	public static function checkCookie(){
		
		if($_COOKIE[SESSION_LOGIN] == hash(METODO_ENCRIPTACION,ENCRYPT_KEY.Login::usuario()->usuario)){
			return true;
		}
	}
	
	/*
	* Formulario donde se introduce el email de la cuenta a resetear la contraseña
	*/
	function formResetPassword(){
		View::render('login','login/recuperar_contrasenya');
	}
	
	/*
	* Recibe el email , comprueba que este registrado en algun usuario.
	* Si lo esta se añade un registro conforme se ha solicitado un cambio de clave.Y la duracion en horas(6) en la cual el enlace que enviaremos por email sera valido.
	* Se envia un email con un string,id usuario y email del usuario a restablecer la contraseña, a validar despues
	*/
	function mailResetPassword(){
		$loginUtils = new LoginUtils();
		$info = Utils::getPost();
		$check = $this->usuariosDao->comprobarEmail($info->mail);
		if($check->result){
			//enviar email ruta
			$val = Utils::randomString('35',true,true);
			if($this->usuariosDao->addRegistroCanvioPassword($check->id,$check->email,$val)){
				$loginUtils->mailResetContrasenya($info->mail,$check->id,$val);
				$msg = "Missatge enviat correctament.Comprovi la seva bústia.";
			};

			//insertar registro
		}else{
			$msg = "E-mail no existeix";	
		}
		echo json_encode($msg);
	}
	
	
	/*
	* Muestra formulario donde introduciremos la nueva contraseña ,si los datos recibidos (rand string,id_usuario,email) son validos
	* comparandolos con el ultimo registro solicitado de canvio de clave.
	*/
	function formNuevaContrasenya($string,$id_usuario,$email){
		$registro = $this->usuariosDao->getUltimaPeticionCanvioClave($email,$id_usuario);
		$hora_actual = date("Y-m-d H:i:s",time());
		$hora_caducidad = $unixTimestamp = strtotime($registro->fecha_caducidad);
		$data = new \stdClass();
		$data->id_usuario = $id_usuario;
		$data->email = $email;
		
		if($hora_actual < $hora_caducidad){
			View::render('login','login/nueva_contrasenya',$data);
		}else{
			View::render('error','error/404');
		}
		
	}
	
	/*
	* 
	*/
	function updateCanviContrasenya(){
		$info = Utils::getPost();
		$password = Utils::setPassword($info->clau);
		if($this->usuariosDao->cambioClaveUsuario($info->usuario,$info->mail,$password)){
			$registro = $this->usuariosDao->getUltimaPeticionCanvioClave($info->mail,$info->usuario);
			$result = $this->usuariosDao->notificarCambioClave($registro->id);
			echo json_encode($result);
		}
	}
	
	/*
	* Destruye variables clase
	*/
	function __destruct(){
		self::$usuariosDao;
	}
	
}

?>
